#include "DualCalendars.h"

#include <core/StyleMgr.h>

#include <QColor>
#include <QCoreApplication>
#include <QHBoxLayout>
#include <QMenu>
#include <QRect>
#include <QStylePainter>
#include <QTableView>
#include <QTextCharFormat>
#include <QToolButton>

DualCalendars::DualCalendars(QWidget* parent /*= nullptr*/, bool isSingle)
    : QFrame(parent, Qt::ToolTip | Qt::BypassGraphicsProxyWidget),
      m_isSingleMode(isSingle),
      m_rcInner(0, 0, 0, 0) {
  m_calL = new SCalendar();
  m_calR = new SCalendar();

  QToolButton* calLMonthButton =
      m_calL->findChild<QToolButton*>(QLatin1String("qt_calendar_monthbutton"));
  QToolButton* calRMonthButton =
      m_calR->findChild<QToolButton*>(QLatin1String("qt_calendar_monthbutton"));
  m_calLmenu = calLMonthButton->menu();
  m_calRmenu = calRMonthButton->menu();

  QHBoxLayout* layout = new QHBoxLayout(this);
  layout->addWidget(m_calL);
  if (!m_isSingleMode) layout->addWidget(m_calR);

  if (m_isSingleMode)
    setFixedSize(232, 238);
  else
    setFixedSize(456, 238);
  setStyleSheet(
      QString("background-color:#%1")
          .arg(StyleMgr::instance().color("BackNormal").rgb(), 0, 16));
  setConnection();
  qApp->installEventFilter(this);
}

DualCalendars::~DualCalendars() {}

void DualCalendars::setConnection() {
  connect(m_calLmenu, &QMenu::aboutToShow, this, &DualCalendars::onMenuShow);
  connect(m_calRmenu, &QMenu::aboutToShow, this, &DualCalendars::onMenuShow);

  connect(m_calLmenu, &QMenu::aboutToHide, this, &DualCalendars::onMenuHide);
  connect(m_calRmenu, &QMenu::aboutToHide, this, &DualCalendars::onMenuHide);

  // 选定日期跟随变化
  connect(m_calL, &QCalendarWidget::clicked, [=](QDate date) {
    onrlClicked(std::make_pair<QString, QDate>("left", std::move(date)));
  });
  connect(m_calR, &QCalendarWidget::clicked, [=](QDate date) {
    onrlClicked(std::make_pair<QString, QDate>("right", std::move(date)));
  });
}

void DualCalendars::setStartEndDate(QDate start, QDate end) {
  QString startDay = start.toString("yyyyMMdd");
  QString endDay = end.toString("yyyyMMdd");

  int sDay = startDay.toInt();
  int eDay = endDay.toInt();

  if (sDay > eDay) std::swap(sDay, eDay);

  emit StartEndDatedSelected(sDay, eDay);
}

void DualCalendars::hideAfterSelected() {
  if (m_isShow) hide();
}

bool DualCalendars::eventFilter(QObject* obj, QEvent* event) {
  if (!isVisible()) return false;
  switch (event->type()) {
    case QEvent::Hide:
    case QEvent::WindowDeactivate: {
      hide();
    } break;
    case QEvent::MouseButtonPress:
    case QEvent::MouseButtonRelease:
    case QEvent::MouseButtonDblClick: {
      if (m_isMenuShow) {
        return false;
      } else {
        QMouseEvent* me = dynamic_cast<QMouseEvent*>(event);
        QPoint pt = me->globalPos();
        pt = mapFromGlobal(pt);
        QPoint ptInner = m_rcInner.topLeft();
        ptInner = mapFromGlobal(ptInner);
        QRect rcInner = m_rcInner;
        rcInner.moveTo(ptInner);
        if (!rect().contains(pt) && !rcInner.contains(pt)) {
          hide();
        }
      }
    } break;
    default:
      break;
  }
  return false;
}

void DualCalendars::paintEvent(QPaintEvent*) {
  QStylePainter painter(this);
  QPen pen(StyleMgr::instance().color("BorderNormal"));
  int r = StyleMgr::instance().size("RoundCorner");

  painter.setRenderHint(QPainter::Antialiasing);
  painter.setPen(pen);

  painter.drawRoundedRect(rect(), r, r);
}

void DualCalendars::onrlClicked(std::pair<QString, QDate> info) {
  if (m_isSingleMode) {
    QString sDate = info.second.toString("yyyyMMdd");
    int nDate = sDate.toInt();

    emit dateSelected(nDate);
    hide();
    return;
  }

  // 清空标注;
  QDate date;
  m_calL->setStart(date);
  m_calR->setStart(date);
  m_calL->setEnd(date);
  m_calR->setEnd(date);

  if (m_selectedDate.dateCountSelected() == 1) {
    m_selectedDate.m_dateSelected.push_back(info);
    if (m_selectedDate.m_dateSelected[0].second >= info.second) {
      if (m_selectedDate.m_dateSelected[0].first == "left") {
        m_calL->setEnd(m_selectedDate.m_dateSelected[0].second);
        m_calR->setEnd(m_selectedDate.m_dateSelected[0].second);
      } else {
        m_calR->setEnd(m_selectedDate.m_dateSelected[0].second);
        m_calL->setEnd(m_selectedDate.m_dateSelected[0].second);
      }
      if (info.first == "right") {
        m_calR->setStart(info.second);
        m_calL->setStart(info.second);
      } else {
        m_calL->setStart(info.second);
        m_calR->setStart(info.second);
      }
      m_calL->setSelectedColorBetweenTwoDatas(
          info.second, m_selectedDate.m_dateSelected[0].second);
      m_calR->setSelectedColorBetweenTwoDatas(
          info.second, m_selectedDate.m_dateSelected[0].second);
    } else {
      if (m_selectedDate.m_dateSelected[0].first == "left") {
        m_calL->setStart(m_selectedDate.m_dateSelected[0].second);
        m_calR->setStart(m_selectedDate.m_dateSelected[0].second);
      } else {
        m_calR->setStart(m_selectedDate.m_dateSelected[0].second);
        m_calL->setStart(m_selectedDate.m_dateSelected[0].second);
      }
      if (info.first == "right") {
        m_calR->setEnd(info.second);
        m_calL->setEnd(info.second);
      } else {
        m_calL->setEnd(info.second);
        m_calR->setEnd(info.second);
      }
      m_calL->setSelectedColorBetweenTwoDatas(
          m_selectedDate.m_dateSelected[0].second, info.second);
      m_calR->setSelectedColorBetweenTwoDatas(
          m_selectedDate.m_dateSelected[0].second, info.second);
    }
    // 调用选择结束，中间单元格上色，选择结果生成
    m_isShow = true;
    if (m_calR->monthShown() <= m_calL->monthShown() ||
        m_calR->yearShown() < m_calL->yearShown()) {
      m_isShow = false;
    }
    if (m_selectedDate.m_dateSelected[0].first == "left" &&
        info.first == "right" &&
        m_selectedDate.m_dateSelected[0].second > info.second) {
      m_isShow = false;
    }

    if (m_isShow)  // 是合法日期再准备发送信号
      setStartEndDate(m_selectedDate.m_dateSelected[0].second, info.second);

    hideAfterSelected();
  } else {
    m_selectedDate.clear();
    // 清除原有标注
    m_calL->setSelectedColorBetweenTwoDatas(QDate(), QDate());
    m_calR->setSelectedColorBetweenTwoDatas(QDate(), QDate());
    // 加入第一个点，等待第二个点
    m_selectedDate.m_dateSelected.push_back(info);
    info.first == "left" ? m_calL->setStart(info.second)
                         : m_calR->setStart(info.second);
  }
}
void DualCalendars::onMenuShow() { m_isMenuShow = true; }

void DualCalendars::onMenuHide() { m_isMenuShow = false; }
